#include "ui_dropdown.h"
#include "ui_manager.h"

#include "lang/lang.h"
#include "font/font.h"

#include "util/timer.h"		    // Needs to come in early
#include "util/mmgr.h"		    // Needs to come in early
#include "util/common_macros.h"		// macros
#include "util/log.h"		    // logging

#include "script/scripthelper.h"
#include "script/write_lua.h"
#ifdef _ENABLE_LUABIND
#include <luabind/luabind.hpp>
#endif // _ENABLE_LUABIND

using namespace ui;
using namespace script;


UIDropDown ::UIDropDown (UIWidget* pParent,const std::string& Name) :
	UIWidget(pParent, Name),
	m_Open(false),
	m_CurrentOption(-1)
{
	m_Type = WT_DROPDOWN;
}

UIDropDown ::~UIDropDown ()
{

}

bool		UIDropDown ::Create(const std::string& Name, const math::Vec2& Pos, const math::Vec2& Size)
{
	UIWidget::Create(Name, Pos, Size);
	// create progress stuff

	return true;
}

bool		UIDropDown ::AddOption(const std::string Option)
{
	UIText	Entry;
	Entry.SetCanEdit(false);
	Entry.SetFont(m_Text.GetFont()->GetName());
	Entry.SetText(lang::Lang::ConvertAtoW(Option));
	Entry.SetHorizJust(UIText::TJH_LEFT);
	Entry.SetColor(m_Text.GetColor());
	Entry.SetOwner(this);
	if (m_CurrentOption < 0)	
	{
		m_CurrentOption = 0;
		SetTextW(Entry.GetText());
	}
	m_Entries.push_back(Entry);
	return true;
}

bool		UIDropDown ::Load(LuaPlus::LuaObject& _LObj)
{
	UIWidget::Load(_LObj);	// get all the common stuff loaded

	
	LuaPlus::LuaObject  Options = _LObj.GetByName("Options");
	if (Options.IsTable())
	{
		for (int i=0; i<Options.GetTableCount(); i++)
		{
			if (Options.GetByIndex(i+1).IsString())
			{
				const char*	Str = Options.GetByIndex(i+1).GetString();
				if (Str)
				{
					AddOption(Str);
				}
			}
		}
	}


	m_CoversCompletely = ScriptHelper::GetTableBool(_LObj, "CoversCompletely", false);

	std::string	 Button = ScriptHelper::GetTableString(_LObj, "DropButton", "");
	std::string	 BG = ScriptHelper::GetTableString(_LObj, "DropBG", "");
	if (!Button.empty())
	{
			m_ImageA[WI_BUTTON].Create(	Button, m_BaseUV1, m_BaseUV2, false);
			m_ImageA[WI_BUTTON].Tick(0);
	}

	if (m_ImageA[WI_BUTTON].IsValid())
	{
		m_ButtonSize = math::Vec2(m_Size.y, m_Size.y);
		m_ButtonPos = m_Pos + math::Vec2(m_Size.x - m_ButtonSize.x, 0);
	} else
	{
		m_ButtonSize = m_Size;
		m_ButtonPos = m_Pos;
	}


	if (!BG.empty())
	{
		m_ImageA[WI_BACKGROUND].Create(	BG, m_BaseUV1, m_BaseUV2, false);
		m_ImageA[WI_BACKGROUND].Tick(0.0f);
	}



	return true;
}

bool		UIDropDown::ExportSpecificsToFile(script::WriteLua*	pWL)
{
	if (m_ImageA[WI_BUTTON].IsValid()) pWL->WritePair("DropButton", m_ImageA[WI_BUTTON].GetFilename());
	if (m_ImageA[WI_BACKGROUND].IsValid()) pWL->WritePair("DropBG", m_ImageA[WI_BACKGROUND].GetFilename());
	if (m_CoversCompletely) pWL->WritePair("CoversCompletely", 1); else pWL->WritePair("CoversCompletely", 0);

	// FIXME: output options
	pWL->StartTable("Options");
	for (int i = 0; i < (int)m_Entries.size(); i++)
	{
		UIText& text = m_Entries[i];
		std::string option = lang::Lang::ConvertWtoA( text.m_OriginalText );
		pWL->WriteNL("\"%s\",", option.c_str());
	}
	pWL->CloseTable(true);
	return true;
}


bool		UIDropDown ::Tick(float dt)
{
	m_ImageA[WI_BUTTON].Tick(dt);
	m_ImageA[WI_BUTTON].Tick(dt);
	UIWidget::Tick(dt);	// tick children, etc
	return true;
}

bool		UIDropDown::ClickInside(const math::Vec2& Pos, const math::Vec2& From, const math::Vec2& Size)
{
	return (UTIL_RANGE(Pos.x, From.x, From.x + Size.x) && UTIL_RANGE(Pos.y, From.y, From.y + Size.y));
}

void		UIDropDown::SetCurrentOptionFromTextW(const std::wstring& Text)
{
	for (unsigned int i=0; i<m_Entries.size(); i++)
	{
		if (m_Entries[i].m_OriginalText == Text) 
		{
			SetCurrentIndex(i, false);
			return;
		}
	}
//	SetCurrentOption(0);
}

void		UIDropDown::SetCurrentOptionFromTextA(const std::string& Text)
{
	SetCurrentOptionFromTextW(lang::Lang::ConvertAtoW(Text));
}

void		UIDropDown::SetCurrentIndex(int index, bool Trigger)
{
	m_CurrentOption = index;
	if (m_CurrentOption >= 0 && m_CurrentOption < (int)m_Entries.size())
	{
		if (!m_CoversCompletely)
			SetTextW(m_Entries[index].GetText());
		else
			SetTextW(L"");
	}
	if (ui::UIManager::Instance().GetSelectedDropDown() == this)
		ui::UIManager::Instance().SetSelectedDropDown(NULL);
	if (Trigger)
	{
		TriggerEvent(WE_TEXT_SELECTED);
	}
}
void		UIDropDown::SetCurrentOption(int index)
{
	SetCurrentIndex(index, false);
}

bool		UIDropDown ::IsInside(const math::Vec2& Pos)
{
	if (m_Open)
	{
		return ClickInside(Pos, m_Pos, math::Vec2(m_Size.x, m_Size.y * (m_Entries.size()+1)));
	} else
	{
		return UIWidget::IsInside(Pos);
	}
}

bool		UIDropDown ::IsImageValid()
{
	return m_ImageA[WI_BACKGROUND].IsValid();
}


bool		UIDropDown ::OnMouseDown(const math::Vec2& Pos, unsigned int Button)
{
	/// assume that all children are inside the volume of the parent?
	if (!m_IsActive || !m_IsVisible)
	{
		return false;
	}

	if (!IsInside(Pos) )
	{
		return false;
	}
	return true;	// it does nothing, but it may cover ones that do
}

bool		UIDropDown ::OnMouseRelease(const math::Vec2& Pos, unsigned int Button)
{
	/// assume that all children are inside the volume of the parent?
	if (!m_IsActive || !m_IsVisible)
	{
		return false;
	}

	if (!IsInside(Pos) )
	{
		return false;
	}


	if (m_Open)
	{
		// did we select something?
		for (unsigned int i=0; i<m_Entries.size(); i++)
		{
			UIText&	Option = m_Entries[i];
			if (ClickInside(Pos, Option.GetPos(), GetSize()))
			{
				m_Open = false;
				SetCurrentIndex(i, true);
				return true;
			}
		}
	}
	if (	ClickInside(Pos, m_ButtonPos, m_ButtonSize) || 
			(m_CoversCompletely && ClickInside(Pos, m_Pos, math::Vec2(m_Size.x + m_ButtonSize.x, m_ButtonSize.y)))
		)
	{
		if (!m_Open)
		{
			m_pManager->SetSelectedDropDown(this);
			m_pManager->PushPanelToFront(this);
		}
		m_Open = !m_Open;
		return true;
	}



	for (ElementList::iterator It = m_Set.begin(); It != m_Set.end(); It++)
	{
		if (It->second->OnMouseDown(Pos, Button))
			return true;
	}

	return false;
}

void		UIDropDown::SetPosition(const math::Vec2& Pos)
{
	math::Vec2	Delta = Pos - GetPositionRelativeToParent();
	m_ButtonPos += Delta;
	UIWidget::SetPosition(Pos);
}


bool		UIDropDown ::Render(bool Force)
{
	if (!UIWidget::Render(Force)) return false;
	// draw button

	m_ImageA[WI_BUTTON].Setup(m_ButtonPos, m_ButtonSize, m_Rotation, m_Scale, m_Color);
	m_ImageA[WI_BUTTON].Render();

	math::Vec2	Offset(m_Size.x * 0.05f, m_Size.y);
	if (m_Open)
	{
		m_ImageA[WI_BACKGROUND].Setup(math::Vec2(m_Pos.x, m_Pos.y + m_Size.y), 
									math::Vec2(m_Size.x, m_Size.y * m_Entries.size()), m_Rotation, m_Scale, m_Color);
		m_ImageA[WI_BACKGROUND].Render();
		for (unsigned int i=0; i<m_Entries.size(); i++)
		{
			UIText&	Option = m_Entries[i];
			math::Vec2 Size = GetSize();
			Option.SetExtents(m_Pos + Offset, Size);
			Option.Render();
			Offset.y += Size.y;
		}
	}
	return true;
}

std::string			UIDropDown ::GetSelectedText()
{
	if (m_CurrentOption == -1 || m_CurrentOption >= (int)m_Entries.size())	return "";
	return lang::Lang::ConvertWtoA(m_Entries[m_CurrentOption].GetText());
}

std::string			UIDropDown ::GetOriginalSelectedText()
{
	if (m_CurrentOption == -1 || m_CurrentOption >= (int)m_Entries.size())	return "";
	return lang::Lang::ConvertWtoA(m_Entries[m_CurrentOption].m_OriginalText);
}

UIWidget*	UIDropDown::GetClone()
{
	UIDropDown*	pNew = new UIDropDown(m_pParent, GetCloneName(m_Name));
	FillCloneInfo((UIWidget*)pNew);
	
	pNew->m_CurrentOption	= this->m_CurrentOption;
	pNew->m_Open			= this->m_Open;
	pNew->m_ButtonPos		= this->m_ButtonPos;
	pNew->m_ButtonSize		= this->m_ButtonSize;

	for (unsigned int i =0; i<m_Entries.size(); i++)
	{
		UIText*		pText = &m_Entries[i];
		AddOption(lang::Lang::ConvertWtoA(pText->m_OriginalText));
	}

	return pNew;
}

void	UIDropDown  ::RefreshText()
{
	UIWidget::RefreshText();
	// update all member variables
	for (unsigned int i=0; i<m_Entries.size(); i++)
		m_Entries[i].RefreshText();
}



void	UIDropDown::RefreshFonts()
{
	UIWidget::RefreshFonts();
	for (unsigned int i=0; i<m_Entries.size(); i++)
		m_Entries[i].SetFont(m_Entries[i].GetFontName());

}

/// register with LUA Bind
void	UIDropDown ::Register(LuaPlus::LuaState* _pScript)
{
 #ifdef _ENABLE_LUABIND
   lua_State * L = _pScript->GetCState ( );

	luabind::module(L)
    [

		luabind::class_<UIDropDown , UIWidget >( "SliderWidget" )
		.def( "GetSelected",				&UIDropDown::GetSelected)
		.def( "GetSelectedText",			&UIDropDown::GetSelectedText)
		.def( "SetCurrentOptionFromText",	&UIDropDown::SetCurrentOptionFromTextA)
		.def( "GetOriginalSelectedText",	&UIDropDown::GetOriginalSelectedText)
		.def( "IsOpen",						&UIDropDown::IsOpen)
		.def( "SetOpen",					&UIDropDown::SetOpen)
		.def( "AddOption",					&UIDropDown::AddOption)
		.def( "Clear",						&UIDropDown::Clear)
		.def( "SetCurrentOption",			&UIDropDown::SetCurrentOption)
	];
#endif // _ENABLE_LUABIND    

}
